package com.zwps.biz.domain.service.impl;

import java.util.Arrays;
import java.util.List;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zwps.biz.dal.db.dao.FileClassDAO;
import com.zwps.biz.dal.db.dao.FileRecordBizDAO;
import com.zwps.biz.dal.db.dao.FileRecordDAO;
import com.zwps.biz.dal.db.object.FileClassDO;
import com.zwps.biz.dal.db.object.FileRecordBizDO;
import com.zwps.biz.dal.db.object.FileRecordDO;
import com.zwps.biz.domain.converter.FileRecordConverter;
import com.zwps.biz.domain.enums.FileDeleteStatusEnum;
import com.zwps.biz.domain.enums.FileStoreTypeEnum;
import com.zwps.biz.domain.enums.FileUploadStatusEnum;
import com.zwps.biz.domain.enums.FileUseTypeEnum;
import com.zwps.biz.domain.service.FileRecordService;
import com.zwps.biz.domain.service.FileStoreService;
import com.zwps.biz.api.model.dto.file.record.SelectFileRecordDTO;
import com.zwps.biz.api.model.dto.file.record.UpdateFileRecordDTO;
import com.zwps.biz.api.model.vo.file.record.FileRecordVO;
import com.zwps.biz.api.model.vo.file.record.FileVO;
import com.zwps.common.api.model.vo.PageInfoVO;
import com.zwps.common.core.exception.UserActionException;
import com.zwps.common.core.service.CommonService;
import com.zwps.common.minio.config.MinioConfigProperties;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;

@Service
@AllArgsConstructor
public class FileRecordServiceImpl implements FileRecordService, CommonService {

    private FileRecordDAO fileRecordDAO;

    private FileStoreService fileStoreService;

    private FileRecordBizDAO fileRecordBizDAO;

    private MinioConfigProperties minioConfig;

    private FileClassDAO fileClassDAO;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addFileRecord(FileRecordDO record) {
        if (fileRecordDAO.insert(record) < 1) {
            throw new UserActionException("保存文件记录失败");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteFileRecords(String ids) {

        List<String> idList = Arrays.asList(ids.split(","));

        for (String s : idList) {
            LambdaQueryWrapper<FileRecordBizDO> wrapper = new QueryWrapper<FileRecordBizDO>().lambda();
            wrapper.eq(FileRecordBizDO::getFileId,s);
            List<FileRecordBizDO> recordBizDOList = fileRecordBizDAO.selectList(wrapper);
            if (!recordBizDOList.isEmpty()) {
                throw new UserActionException("该文件已绑定关联，删除失败");
            }

            LambdaQueryWrapper<FileRecordDO> fileRecordWrapper = new QueryWrapper<FileRecordDO>().lambda();
            fileRecordWrapper.and(wapper -> wapper.eq(FileRecordDO::getParentId,s).or().eq(FileRecordDO::getId,s));
            Long count = fileRecordDAO.selectCount(fileRecordWrapper);
            int delete = fileRecordDAO.delete(fileRecordWrapper);

            if (delete != count) {
                throw new UserActionException("删除文件失败");
            }
        }

        fileRecordBizDAO.delete(Wrappers.lambdaQuery(FileRecordBizDO.class).in(FileRecordBizDO::getFileId, idList));

//        LambdaUpdateWrapper<FileRecordDO> update = Wrappers.lambdaUpdate(FileRecordDO.class);
//        update.set(FileRecordDO::getDeleteStatus, FileDeleteStatusEnum.DELETED.getCode());
//        update.in(FileRecordDO::getId, idList);
//        int result = fileRecordDAO.update(null, update);
//        if (result != idList.size()) {
//            LambdaQueryWrapper<FileRecordDO> query = Wrappers.lambdaQuery(FileRecordDO.class)
//                    .in(FileRecordDO::getId, idList)
//                    .eq(FileRecordDO::getDeleteStatus, FileDeleteStatusEnum.DELETED.getCode());
//            long FileRecordNum = fileRecordDAO.selectCount(query);
//            if (FileRecordNum > 0) {
//                log.error("Delete FileRecords id[{}] fail, select item {}, delete success {}", ids, idList.size(),
//                        result);
//                throw new UserActionException("删除失败");
//            }
//        }

    }

    @Override
    public PageInfoVO<FileRecordVO> selectFileRecords(SelectFileRecordDTO dto) {
        LambdaQueryWrapper<FileRecordDO> query = Wrappers.lambdaQuery(FileRecordDO.class);
        query.eq(FileRecordDO::getDeleteStatus, FileDeleteStatusEnum.NORMAL.getCode());
        query.like(StrUtil.isNotEmpty(dto.getFileName()), FileRecordDO::getFileName, dto.getFileName());
        query.like(StrUtil.isNotEmpty(dto.getFilePath()), FileRecordDO::getFilePath, dto.getFilePath());
        query.like(StrUtil.isNotEmpty(dto.getFileUrl()), FileRecordDO::getFileUrl, dto.getFileUrl());
        query.like(StrUtil.isNotEmpty(dto.getFileType()), FileRecordDO::getFileType, dto.getFileType());
        query.eq(dto.getStoreType() != null, FileRecordDO::getStoreType, dto.getStoreType());
        query.eq(dto.getUploadStatus() != null, FileRecordDO::getUploadStatus, dto.getUploadStatus());
        query.eq(dto.getExternalFile() != null, FileRecordDO::getExternalFile, dto.getExternalFile());
        query.eq(StringUtils.isNotBlank(dto.getFileClass()), FileRecordDO::getFileClass, dto.getFileClass());
        query.like(StrUtil.isNotEmpty(dto.getUploadFailReason()), FileRecordDO::getUploadFailReason,
                dto.getUploadFailReason());
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        List<FileRecordDO> list = fileRecordDAO.selectList(query);

        List<FileRecordVO> fileRecordVOList = FileRecordConverter.INSTANCE.toFileUploadInfoVO(list);
        Page<FileRecordDO> page = (Page<FileRecordDO>) list;
        PageInfoVO<FileRecordVO> pageInfo = new PageInfoVO<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(),
                fileRecordVOList);


        for (FileRecordVO fileRecordVO : fileRecordVOList) {
            FileClassDO fileClassDO = fileClassDAO.selectById(fileRecordVO.getFileClass());
            if (fileClassDO != null) {
                fileRecordVO.setFileClassName(fileClassDO.getFileClassName());
            }

            if (fileRecordVO.getStoreType() != null) {
                for (FileStoreTypeEnum value : FileStoreTypeEnum.values()) {
                    if (value.getCode().equals(fileRecordVO.getStoreType())) {
                        fileRecordVO.setStoreTypeName(value.getName());
                    }
                }
            }

            if (fileRecordVO.getUploadStatus() != null) {
                for (FileUploadStatusEnum value : FileUploadStatusEnum.values()) {
                    if (value.getCode().equals(fileRecordVO.getUploadStatus())) {
                        fileRecordVO.setUploadStatusName(value.getName());
                    }
                }
            }

            if (fileRecordVO.getUseType() != null) {
                for (FileUseTypeEnum value : FileUseTypeEnum.values()) {
                    if (value.getCode().equals(fileRecordVO.getUseType())) {
                        fileRecordVO.setUseTypeName(value.getName());
                    }
                }
            }

        }

        return pageInfo;
    }

    @Override
    public FileVO selectFileByFileId(String id) {
        FileVO fileVO = FileRecordConverter.INSTANCE.toFileVO(fileRecordDAO.selectById(id));
        fileVO.setFileInternalUrl(minioConfig.getInternalUrl() + "/" + fileVO.getFilePath());
        if (fileVO.getExternalFile() == null || fileVO.getExternalFile() == 0) {
            fileVO.setFileUrl(minioConfig.getExternalUrl() + "/" + fileVO.getFilePath());
        }
        return fileVO;
    }

    @Override
    public void updateFileRecord(String id, UpdateFileRecordDTO dto) {
        FileRecordDO fileRecordDO = fileRecordDAO.selectById(id);
        if (fileRecordDO == null) {
            throw new UserActionException("修改的文件记录不存在");
        }

        if (fileRecordDO.getExternalFile() == 0) {
            throw new UserActionException("非外部文件不可修改");
        }

        LambdaUpdateWrapper<FileRecordDO> update = Wrappers.lambdaUpdate(FileRecordDO.class);
        update.set(change(dto.getFileName(), fileRecordDO.getFileName()), FileRecordDO::getFileName, dto.getFileName());
        update.set(change(dto.getFileUrl(), fileRecordDO.getFileUrl()), FileRecordDO::getFileUrl, dto.getFileUrl());

        if (StrUtil.isNotEmpty(update.getSqlSet())) {
            update.eq(FileRecordDO::getId, id);
            if (fileRecordDAO.update(null, update) < 1) {
                throw new UserActionException("修改文件记录失败");
            }
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteFileRecord(String id) {
        FileRecordDO record = fileRecordDAO.selectById(id);
        if (record == null) {
            return;
        }
        if (FileDeleteStatusEnum.DELETED.getCode().equals(record.getDeleteStatus())) {
            return; // 已经是逻辑删除的记录，交给异步处理程序
        }
        if (FileUploadStatusEnum.UPLOADING.getCode().equals(record.getUploadStatus())) {
            throw new UserActionException("文件正在上传，不能删除");
        }
        if (fileRecordDAO.deleteById(id) < 1) {
            throw new UserActionException("删除文件记录失败");
        }
        if (StrUtil.isNotEmpty(record.getFilePath())) {
            fileStoreService.delete(record.getFilePath());
        }
        fileRecordBizDAO.delete(Wrappers.lambdaQuery(FileRecordBizDO.class).eq(FileRecordBizDO::getFileId, id));
    }
}
